package igin

import (
	"context"
	"fmt"
	"gitee.com/tietang/terrace-go/v2/base"
	"github.com/gin-gonic/gin"
	log "github.com/sirupsen/logrus"
	"github.com/tietang/props/v3/kvs"
	"net/http"
	"time"
)

//gin 应用程序管理器

var ginEngine *gin.Engine

//全局暴露
func Gin() *gin.Engine {
	base.Check(ginEngine)
	return ginEngine
}

func initGin(conf kvs.ConfigSource) *gin.Engine {
	gin.EnableJsonDecoderDisallowUnknownFields()
	gin.EnableJsonDecoderUseNumber()
	gin.ForceConsoleColor()
	r := gin.Default()
	r.Use(Logger(log.StandardLogger()))
	r.Use(gin.LoggerWithConfig(gin.LoggerConfig{
		Output: new(logrusOut),
	}))
	r.Use(gin.Recovery())
	gin.DebugPrintRouteFunc = func(httpMethod, absolutePath, handlerName string, nuHandlers int) {
		log.Infof("endpoint: %v %v %v %v\n", httpMethod, absolutePath, handlerName, nuHandlers)
	}
	//gin.DefaultWriter = log.StandardLogger().Out
	//gin.DefaultErrorWriter = log.StandardLogger().Out
	return r
}

type GinServerStarter struct {
	base.BaseStarter
	srv  *http.Server
	addr string
}

func (s *GinServerStarter) Init(ctx base.StarterContext) {
	ginEngine = initGin(ctx.Props())
	fmt.Println("gin")
}
func (s *GinServerStarter) Setup(ctx base.StarterContext) {}
func (s *GinServerStarter) Start(ctx base.StarterContext) {

	port := ctx.Props().GetDefault("app.server.port", "8080")
	addr := ":" + port
	outAddr := "0.0.0.0:" + port
	srv := &http.Server{
		Addr:    addr,
		Handler: Gin(),
	}
	s.srv = srv
	s.addr = outAddr

	log.Info("Gin listening on: ", outAddr)
	// 服务连接
	if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
		log.Fatalf("listen: %s\n", err)
	}

}

func (s *GinServerStarter) StartBlocking() bool { return true }
func (s *GinServerStarter) Stop(ctx base.StarterContext) {
	contx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	if err := s.srv.Shutdown(contx); err != nil {
		log.Fatal("Server Shutdown:", err)
	}
	log.Info("gin server shutdown on: ", s.addr)

}

type logrusOut struct {
}

func (l *logrusOut) Write(p []byte) (n int, err error) {
	log.Info(p)
	return len(p), nil
}

type BaseGinApi struct {
	GroupRouter *gin.RouterGroup
}
